package web

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
	"mts/trans_srv/internal/domain"
	"mts/trans_srv/internal/service"
	middleware "mts/trans_srv/internal/web/middleware"
	"net/http"
	"strconv"
	"time"
)

const (
	ActionDeleteElem ActionType = "删除组件"
	ActionUpdateElem ActionType = "更新组件"
	ActionAddElem    ActionType = "创建组件"
)

type ElementHandler struct {
	svc service.ElementService
}

func NewElementHandler(svc service.ElementService) *ElementHandler {
	return &ElementHandler{
		svc: svc,
	}
}
func (h *ElementHandler) RegisterRoutes(group *gin.RouterGroup) {
	elementGroup := group.Group("/element").Use(middleware.JWTAuth())
	{
		elementGroup.GET("/", middleware.IsAdminAuth(), h.List)
		elementGroup.POST("/", middleware.IsAdminAuth(), h.Insert)
		elementGroup.GET("/:eid", middleware.IsAdminAuth(), h.FindElementByID)
		elementGroup.DELETE("/:eid", middleware.IsAdminAuth(), h.DeleteById)
		elementGroup.PUT("/:eid", middleware.IsAdminAuth(), h.EditById)
		elementGroup.GET("/trans/list", middleware.IsAdminAuth(), h.GetCustomFormattedTranslations)
		//插入和更新组件和翻译
		elementGroup.POST("/save", middleware.IsAdminAuth(), h.AddElementAndTranslation)
		//导出
		elementGroup.GET("/export", h.ExportExcelWithAllElementAndTranslation)
		//导入
		elementGroup.POST("/import", middleware.IsAdminAuth(), h.ImportExcelWithAllElementAndTranslation)
		//返回组件总数
		elementGroup.GET("/count", h.Count)
	}
}

func (h *ElementHandler) List(ctx *gin.Context) {
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("pageSize", "10"))
	if list, err := h.svc.List(ctx, page, pageSize); err != nil {
		ctx.JSON(http.StatusOK, gin.H{"msg": "获取组件列表异常"})
		return
	} else {
		ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "成功", "data": list})
	}
}

// Insert 新增组件
func (h *ElementHandler) Insert(ctx *gin.Context) {
	var info domain.CreateElement
	if err := ctx.ShouldBindJSON(&info); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"msg": "参数错误"})
		return
	}

	if err := h.svc.Insert(ctx, info); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code": 500,
			"msg":  "插入失败"})
		return
	} else {
		h.SendMessage(ctx, ActionAddElem, TypeCreate, fmt.Sprintf("创建了%s组件", info.Name))
		ctx.JSON(http.StatusOK, gin.H{
			"code": 200,
			"msg":  "添加成功",
		})
	}
}

//

// FindElementByID 获取单个组件的信息
func (h *ElementHandler) FindElementByID(ctx *gin.Context) {
	id := ctx.Param("eid")
	//校验组件信息
	if element, err := h.svc.FindElementByID(ctx, id); err != nil {
		ctx.JSON(http.StatusOK, gin.H{"msg": "获取组件信息失败"})
		return
	} else {
		ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "成功", "data": element})
	}
}

// DeleteById 根据组件id 删除组件
func (h *ElementHandler) DeleteById(ctx *gin.Context) {
	id := ctx.Param("eid")
	info, _ := h.svc.FindElementByID(ctx, id)
	if err := h.svc.DeleteById(ctx, id); err != nil {
		ctx.JSON(http.StatusOK, gin.H{"msg": "删除组件失败"})
		return
	} else {
		h.SendMessage(ctx, ActionDeleteElem, TypeDelete, fmt.Sprintf("删除了%s组件", info.Name))
		ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "删除组件成功"})
	}
}

func (h *ElementHandler) EditById(ctx *gin.Context) {
	var elementInfo domain.Element
	//1.校验
	if err := ctx.ShouldBindJSON(&elementInfo); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"msg": "参数错误"})
		return
	}
	//2.检查id是否存在
	if ele, err := h.svc.FindElementByID(ctx, elementInfo.ID); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "系统异常"})
		return
	} else {
		if &ele == nil {
			ctx.JSON(http.StatusOK, gin.H{"msg": "组件不存在"})
			return
		}
	}
	if err := h.svc.EditById(ctx, ctx.Param("id"), elementInfo); err != nil {
		ctx.JSON(http.StatusOK, gin.H{"msg": "修改组件失败"})
		return
	} else {
		h.SendMessage(ctx, ActionUpdateElem, TypeUpdate, fmt.Sprintf("更新了%s组件", elementInfo.Name))
		ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "修改组件成功"})
	}
}

// GetCustomFormattedTranslations 后端管理界面提供所有组件与翻译相关信息
func (h *ElementHandler) GetCustomFormattedTranslations(ctx *gin.Context) {
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("pageSize", "10"))
	// 获取自定义格式化的翻译
	elements, err := h.svc.GetCustomFormattedTranslations(ctx, page, pageSize)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "组件列表获取失败"})
		return
	}
	count, _ := h.svc.GetListCount(ctx)

	ctx.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "成功",
		"data":    elements,
		"total":   count,
	})
}

func (h *ElementHandler) AddElementAndTranslation(ctx *gin.Context) {
	var createElementInfo domain.CreateElementAndTranslationInfo
	if err := ctx.ShouldBindJSON(&createElementInfo); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"msg": "参数错误"})
		return
	}

	if err := h.svc.AddElementAndTranslation(ctx, createElementInfo); err != nil {
		ctx.JSON(http.StatusOK, gin.H{"msg": "操作失败"})
		return
	}
	if createElementInfo.ID == "" {
		h.SendMessage(ctx, ActionAddElem, TypeCreate, fmt.Sprintf("创建了%s组件", createElementInfo.Name))
	} else {
		h.SendMessage(ctx, ActionUpdateElem, TypeUpdate, fmt.Sprintf("更新了%s组件", createElementInfo.Name))
	}
	ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "操作成功"})
}

// ExportExcelWithAllElementAndTranslation 导出组件和翻译
func (h *ElementHandler) ExportExcelWithAllElementAndTranslation(ctx *gin.Context) {
	list, err := h.svc.GetCustomFormattedTranslations(ctx, 0, 0)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "导出失败"})
		return
	}

	// 创建Excel文件
	f := excelize.NewFile()
	sheetName := "Sheet1"
	index, err := f.NewSheet(sheetName)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "新建表格失败"})
		return
	}

	// 写入表头
	headers := []interface{}{"Name", "Type", "Description"}
	if len(*list) > 0 {
		for lang := range (*list)[0].Translations {
			headers = append(headers, lang)
		}
	}
	f.SetSheetRow(sheetName, "A1", &headers)

	// 写入数据行
	for i, element := range *list {
		row := []interface{}{element.Name, element.Type, element.Description}
		for _, lang := range headers[3:] {
			translation, exists := element.Translations[lang.(string)]
			if exists {
				row = append(row, translation)
			} else {
				row = append(row, "") // 如果没有翻译内容，写入空字符串
			}
		}
		cell, _ := excelize.CoordinatesToCellName(1, i+2)
		f.SetSheetRow(sheetName, cell, &row)
	}

	// 设置默认工作表
	f.SetActiveSheet(index)

	// 将Excel文件写入到内存
	buf, err := f.WriteToBuffer()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "写入文件失败"})
		return
	}

	// 设置响应头
	ctx.Header("Content-Type", "application/octet-stream")
	ctx.Header("Content-Disposition", "attachment; filename=elements_"+time.Now().Format("20060102_150405")+".xlsx")
	ctx.Header("File-Name", "elements_"+time.Now().Format("20060102_150405")+".xlsx")
	ctx.Header("Content-Transfer-Encoding", "binary")
	ctx.Header("Expires", "0")
	// 返回Excel文件
	ctx.Data(http.StatusOK, "application/octet-stream", buf.Bytes())
}

func (h *ElementHandler) ImportExcelWithAllElementAndTranslation(ctx *gin.Context) {
	// 获取上传的文件
	file, err := ctx.FormFile("file")
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"msg": "文件上传失败"})
		return
	}

	// 打开上传的文件
	src, err := file.Open()
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "打开文件失败"})
		return
	}
	defer src.Close()

	// 读取Excel文件
	f, err := excelize.OpenReader(src)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "读取Excel文件失败"})
		return
	}

	// 获取第一个工作表
	sheetName := f.GetSheetName(0)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "获取工作表失败"})
		return
	}

	// 获取表头
	rows, err := f.GetRows(sheetName)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "读取行失败"})
		return
	}

	if len(rows) == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"msg": "Excel文件为空"})
		return
	}

	headers := rows[0]
	dataRows := rows[1:]

	// 解析数据
	var elements []domain.CreateElementAndTranslationInfo
	for _, row := range dataRows {
		if len(row) < 3 {
			ctx.JSON(http.StatusBadRequest, gin.H{"msg": "数据格式错误"})
			return
		}
		element := domain.CreateElementAndTranslationInfo{
			Name:         row[0],
			Type:         row[1],
			Description:  row[2],
			Translations: make(map[string]string),
		}

		for i := 3; i < len(row); i++ {
			if i-3 < len(headers)-3 {
				element.Translations[headers[i]] = row[i]
			}
		}

		elements = append(elements, element)
	}

	// 保存数据到数据库
	for _, element := range elements {
		if err := h.svc.AddElementAndTranslation(ctx, element); err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{"msg": "保存数据失败"})
			return
		}
	}
	ctx.JSON(http.StatusOK, gin.H{"code": 200, "msg": "导入成功"})
}

func (h *ElementHandler) getCurrentUser(ctx *gin.Context) *domain.CustomClaims {
	claims, _ := ctx.Get("claims")
	return claims.(*domain.CustomClaims)
}

func (h *ElementHandler) SendMessage(ctx *gin.Context, a ActionType, t LogType, d string) {
	currentUser := h.getCurrentUser(ctx)
	//发送消息到rabbitmq服务
	err := h.svc.Publish(map[string]interface{}{
		"user_id":   currentUser.NickName,
		"action":    a,
		"type":      t,
		"details":   d,
		"timestamp": time.Now(),
	})
	if err != nil {
		zap.S().Errorf("记录日志失败:%s", err)
	}
}

func (h *ElementHandler) Count(ctx *gin.Context) {
	count, err := h.svc.GetListCount(ctx)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": 400,
			"msg":  "系统异常",
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"element": count,
	})
}
